package com.yata.utils.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

/**
 * Created by hecy on 2018/1/25.
 */
public class PictureWithWord {

    private Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 设置默认字体 大小
     */
    private static Font font = new Font("楷体", Font.PLAIN, 40);

    private static Graphics2D g2d = null;

    private int fontSize = 0;

    private int x = 0;

    private int y = 0;

    /**
     * 设定全局文字的字体等
     */
    public void setGlobalFont(String fontStyle, int style, int fontSize) {
        logger.info("设置全局字体样式。字体【{}】，类型【{}】，大小【{}】", fontStyle, style, fontSize);
        this.fontSize = fontSize;
        font = new Font(fontStyle, style, fontSize);
    }

    private void setGlobalGraphics2D(BufferedImage img, Color fontColor) {
        g2d = img.createGraphics();
        g2d.setColor(fontColor);
        if (font != null)
            g2d.setFont(font);
    }

    /**
     * 导入本地图片到缓冲区
     */
    public BufferedImage loadImageLocal(String imgName) {
        try {
            logger.info("导入本地图片到缓冲区：" + imgName);
            return ImageIO.read(new File(imgName));
        } catch (IOException e) {
            logger.error("导入本地图片出现异常：" + e.getMessage(), e);
        }
        return null;
    }

    /**
     * 生成新图片到本地
     */
    public boolean writeImageLocal(String newImage, BufferedImage img) {
        logger.info("生成新图片到本地开始" + newImage);
        boolean result = false;
        if (newImage != null && img != null) {
            try {
                String format = newImage.substring(newImage.lastIndexOf(".") + 1, newImage.length());
                File outPutFile = new File(newImage);
                result = ImageIO.write(img, format, outPutFile);
            } catch (IOException e) {
                logger.error("生成新图片到本地：" + e.getMessage(), e);
            }
        }
        return result;
    }


    /**
     * 获取需求写到图片上的文字最终换行的结果。
     *
     * @param b          目标文件
     * @param str        要写的文字
     * @param startWidth 文字写在图片上的起始坐标
     * @param endWidth   横坐标写上文字后需要有多少长度
     * @return
     */
    public String[] getStringArray(BufferedImage b, String str,
                                   int startWidth, int endWidth) {
        try {
            logger.info("转换成换行后的文字");
            int width = b.getWidth();
            if (width > (startWidth + endWidth)) {
                width = width - startWidth - endWidth;
            } else if (width > startWidth) {
                width = width - startWidth;
            }
            int height = b.getHeight();
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

            Graphics g = image.getGraphics();
            g.fillRect(0, 0, width, height);
            g.setFont(font);
            // 得到当前的font metrics
            FontMetrics metrics = g.getFontMetrics();
            int StrPixelWidth = metrics.stringWidth(str); // 字符串长度（像素） str要打印的字符串
            int lineSize = (int) Math.ceil(StrPixelWidth * 2 / width);// 算出行数
            String tempStrs[] = new String[lineSize];// 存储换行之后每一行的字符串
            if (width < StrPixelWidth) {// 页面宽度（width）小于 字符串长度
                StringBuilder sb = new StringBuilder();// 存储每一行的字符串
                int j = 0;
                int tempStart = 0;
                for (int i = 0; i < str.length(); i++) {
                    char ch = str.charAt(i);
                    sb.append(ch);
                    Rectangle2D bounds2 = metrics.getStringBounds(sb.toString(), null);
                    int tempStrPi1exlWi1dth = (int) bounds2.getWidth();
                    if (tempStrPi1exlWi1dth > width) {
                        tempStrs[j++] = str.substring(tempStart, i);
                        tempStart = i;
                        sb.delete(0, sb.length());
                        sb.append(ch);
                    }
                    if (i == str.length() - 1) { //最后一行
                        tempStrs[j] = str.substring(tempStart);
                    }
                }

            } else {
                tempStrs = new String[1];
                tempStrs[0] = str;
            }

            return tempStrs;

        } catch (Exception e) {
            logger.error("获取需求写到图片上的文字最终换行的结果出现异常：" + e.getMessage(), e);
            return new String[0];
        }
    }

    /**
     * 修改图片,返回修改后的图片缓冲区（只输出一行文本）
     */
    public BufferedImage modifyImage(BufferedImage img, Object content, Color fontColor, int x, int y) {

        try {
            logger.info("content: "+ content);
            setGlobalGraphics2D(img, fontColor);

            int w = img.getWidth();
            int h = img.getHeight();

            // 验证输出位置的纵坐标和横坐标
            if (x >= h || y >= w) {
                this.x = h - this.fontSize + 2;
                this.y = w;
            } else {
                this.x = x;
                this.y = y;
            }
            if (content != null) {
                this.g2d.drawString(content.toString(), this.x, this.y);
            }
            this.g2d.dispose();
        } catch (Exception e) {
            logger.error("修改图片,返回修改后的图片缓冲区出现异常：" + e.getMessage(), e);
        }
        return img;
    }


    /**
     * 图片上写文字
     *
     * @param sourceImgPath 原始图片路径
     * @param targetImgPath 目标文件路径
     * @param context       写在图片上的文字
     * @param startWidth    文字在图片上的起始横坐标
     * @param endWidth      文字在图片上的结束横坐标
     * @param startHeight   文字在图片的起始树坐标
     * @param rowSpacing    文字换行后行间距
     */
    public void writeImageWithWord(String sourceImgPath, String targetImgPath,
                                   String context, int startWidth, int endWidth,
                                   int startHeight, int rowSpacing, Color fontColor) {
        logger.info("在图片上写文字开始。");
        logger.info("原始文件【{}】", sourceImgPath);
        logger.info("目标文件【{}】", targetImgPath);
        PictureWithWord pww = new PictureWithWord();
        BufferedImage d = pww.loadImageLocal(sourceImgPath);
        int fontHeight = (int) font.getSize2D();
        String strArr[] = getStringArray(d, context, startWidth, endWidth);
        BufferedImage bfi = null;

        for (int i = 0; i < strArr.length; i++) {
            if (strArr[i] != null) {
                bfi = pww.modifyImage(d, strArr[i], fontColor, startWidth,
                        startHeight + (fontHeight + rowSpacing) * (i + 1));
            }
        }
        pww.writeImageLocal(targetImgPath, bfi);
        logger.info("在图片上写文字结束。");

    }

    public static void main(String[] args) {
        String str = "写作是运用语言文字符号反映客观事物、表达思想感情、" +
                "传递知识信息的创造性脑力劳动过程。作为一个完整的系统过程，" +
                "写作活动大致可分为“采集—构思—表述”三个阶段。与作家的自由写" +
                "作、职业人群的专业写作不同，语文课程意义的写作，是学生在教师" +
                "指导下按照特定要求用书面语言创造文本，以发展和提高自身写作能" +
                "力的学习活动。简单来说，写作是生活中与人沟通、交流、分享信息的" +
                "一种方式，就像我们平常说话一样。写作就是用笔来说话";

        String str2 = "写作就是用笔来说话";
        PictureWithWord tt = new PictureWithWord();
        tt.setGlobalFont("楷书", Font.BOLD, 30);
        String sourceImgPath = "C:\\Users\\hecy\\Desktop\\imgtest\\02212317_h.jpg";
        String targetImgPath = "C:\\Users\\hecy\\Desktop\\imgtest\\ll.jpg";
        tt.writeImageWithWord(sourceImgPath, targetImgPath,
                str, 100, 100, 100, 10, Color.RED);
        tt.logger.info("在图片上写文字开始。目标文件【{}】", sourceImgPath);
    }


}
